import os
import json
import requests
from requests.exceptions import RequestException
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import time

# 导入路径工具函数
from backend.utils.path_helper import find_latest_alarm_excel

# 导出函数供其他模块使用
__all__ = ['analyze_excel_file', 'call_local_llm', 'generate_markdown_report', 'analyze_dataframe']

def call_local_llm(analysis_results):
    try:
        # Ollama API配置
        llm_api_url = "http://localhost:11434/api/generate"  # Ollama的默认API端点
        
        # 构建提示词
        prompt = f"""作为一个专业的告警分析专家，请分析以下告警数据并提供见解：

告警数据概览：
1. TOP20告警标题：{json.dumps(analysis_results['top20_alarm_titles'], ensure_ascii=False)}
2. 告警级别分布：{json.dumps(analysis_results['alarm_levels'], ensure_ascii=False)}
3. 设备类型分布：{json.dumps(analysis_results['device_types'], ensure_ascii=False)}
4. 设备厂商分布：{json.dumps(analysis_results['device_vendors'], ensure_ascii=False)}

请从以下几个方面进行分析：
1. 告警标题趋势分析：分析主要告警标题类型及其分布情况,告警标题详细数据
```json
{json.dumps(analysis_results['top20_alarm_titles'], ensure_ascii=False, indent=2)}
```
2. 告警级别分析：分析不同级别告警的分布和影响,告警级别详细数据
```json
{json.dumps(analysis_results['alarm_levels'], ensure_ascii=False, indent=2)}
```
3. 设备分析：分析设备类型和厂商的分布特点,设备类型详细数据,设备厂商（虚层）详细数据
```json
{json.dumps(analysis_results['device_types'], ensure_ascii=False, indent=2)}
```
```json
{json.dumps(analysis_results['device_vendors'], ensure_ascii=False, indent=2)}
```
4. 改进建议：基于分析结果提出具体的改进建议


请用中文回答，并确保分析专业、客观、具体。"""
        
        # 构建请求数据 - 使用Ollama API格式
        data = {
            "model": "qwen3:14b",
            "prompt": prompt,
            "stream": True,  # 启用流式响应
            "options": {
                "temperature": 0.7,
                "top_p": 0.9,
                "num_predict": 2000
            }
        }
        
        # 发送请求
        print("正在调用Qwen模型进行分析...")
        headers = {
            "Content-Type": "application/json"
        }
        
        # 打印请求信息以便调试
        print(f"API URL: {llm_api_url}")
        print(f"Request Headers: {headers}")
        print(f"Request Data: {json.dumps(data, ensure_ascii=False, indent=2)}")
        
        # 添加重试机制
        max_retries = 3
        retry_delay = 5  # 重试间隔（秒）
        
        for attempt in range(max_retries):
            try:
                print(f"尝试第 {attempt + 1} 次请求...")
                response = requests.post(
                    llm_api_url,
                    headers=headers,
                    json=data,
                    timeout=180,  # 增加超时时间到3分钟
                    stream=True  # 启用流式响应
                )
                
                # 打印响应信息以便调试
                print(f"Response Status: {response.status_code}")
                print(f"Response Headers: {dict(response.headers)}")
                
                if response.status_code == 200:
                    try:
                        full_response = ""
                        print("\n开始接收模型响应...")
                        for line in response.iter_lines():
                            if line:
                                try:
                                    chunk = json.loads(line)
                                    if 'response' in chunk:
                                        response_text = chunk['response']
                                        full_response += response_text
                                        print(response_text, end="", flush=True)  # 实时显示响应内容
                                except json.JSONDecodeError:
                                    continue
                        
                        print("\n\n成功获取完整响应")
                        print("\n完整响应内容：")
                        print("-" * 80)
                        print(full_response)
                        print("-" * 80)
                        
                        # 保存响应到文件
                        try:
                            output_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'analysis_results')
                            os.makedirs(output_dir, exist_ok=True)
                            response_file = os.path.join(output_dir, 'model_response.txt')
                            with open(response_file, 'w', encoding='utf-8') as f:
                                f.write(full_response)
                            print(f"\n响应内容已保存到: {response_file}")
                        except Exception as e:
                            print(f"\n保存响应内容时出错: {str(e)}")
                        
                        if full_response:
                            return full_response
                        else:
                            print("响应内容为空")
                            if attempt < max_retries - 1:
                                print(f"等待 {retry_delay} 秒后重试...")
                                time.sleep(retry_delay)
                                continue
                            return "无法获取分析结果"
                            
                    except Exception as e:
                        print(f"处理响应时出错: {str(e)}")
                        if attempt < max_retries - 1:
                            print(f"等待 {retry_delay} 秒后重试...")
                            time.sleep(retry_delay)
                            continue
                        return f"处理响应时出错: {str(e)}"
                else:
                    print(f"调用Qwen模型失败: {response.status_code}")
                    print(f"错误响应: {response.text}")
                    if attempt < max_retries - 1:
                        print(f"等待 {retry_delay} 秒后重试...")
                        time.sleep(retry_delay)
                        continue
                    return "Qwen模型分析失败，请检查API配置"
                    
            except requests.exceptions.Timeout:
                print(f"请求超时 (尝试 {attempt + 1}/{max_retries})")
                if attempt < max_retries - 1:
                    print(f"等待 {retry_delay} 秒后重试...")
                    time.sleep(retry_delay)
                    continue
                raise
            except requests.exceptions.RequestException as e:
                print(f"请求异常: {str(e)}")
                if attempt < max_retries - 1:
                    print(f"等待 {retry_delay} 秒后重试...")
                    time.sleep(retry_delay)
                    continue
                raise
            
    except Exception as e:
        print(f"调用Qwen模型时出错: {str(e)}")
        return f"Qwen模型调用出错: {str(e)}"

def generate_markdown_report(analysis_results, file_path, output_dir):
    try:
        # 生成时间戳
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        print(f"开始生成Markdown报告...")
        print(f"输出目录: {output_dir}")
        
        # 调用本地大模型进行分析
        print("正在调用本地大模型进行分析...")
        llm_analysis = call_local_llm(analysis_results)
        
        # 创建Markdown内容
        markdown_content = f"""# 工作台西北大区资源池历史告警分析报告

## 基本信息
- 文件名：{os.path.basename(file_path)}
- 分析时间：{timestamp}

## 智能分析结果
{llm_analysis}

## 附录：原始图表数据

### 告警标题原始数据
![告警标题统计](top20_alarm_titles.png)
#### 告警标题详细数据
```json
{json.dumps(analysis_results['top20_alarm_titles'], ensure_ascii=False, indent=2)}
```

### 告警级别原始数据
![告警级别分布](alarm_levels.png)
#### 告警级别详细数据
```json
{json.dumps(analysis_results['alarm_levels'], ensure_ascii=False, indent=2)}
```

### 设备类型原始数据
![设备类型分布](device_types.png)
#### 设备类型详细数据
```json
{json.dumps(analysis_results['device_types'], ensure_ascii=False, indent=2)}
```

### 设备厂商（虚层）原始数据
![设备厂商分布](device_vendors.png)
#### 设备厂商（虚层）详细数据
```json
{json.dumps(analysis_results['device_vendors'], ensure_ascii=False, indent=2)}
```
"""
        
        # 确保输出目录存在
        os.makedirs(output_dir, exist_ok=True)
        print(f"确认输出目录存在: {output_dir}")
        
        # 保存Markdown文件
        markdown_path = os.path.join(output_dir, 'analysis_report.md')
        print(f"准备保存Markdown文件到: {markdown_path}")
        
        with open(markdown_path, 'w', encoding='utf-8') as f:
            f.write(markdown_content)
        
        print(f"Markdown文件已保存: {markdown_path}")
        
        # 验证文件是否成功保存
        if os.path.exists(markdown_path):
            print(f"确认文件已成功保存，文件大小: {os.path.getsize(markdown_path)} 字节")
        else:
            print("警告：文件似乎没有成功保存！")
        
        return markdown_path
    except Exception as e:
        print(f"生成Markdown报告时出错: {str(e)}")
        raise

def analyze_dataframe(df, output_dir=None):
    """
    分析DataFrame数据并生成analysis_results
    
    Args:
        df: pandas DataFrame，必须包含以下列：
            - '告警标题'
            - '标准告警级别'
            - '设备类型'
            - '设备厂商（虚层）'
        output_dir: 输出目录，如果提供则生成柱状图PNG文件
    
    Returns:
        dict: analysis_results 字典，包含四种分析结果
    """
    try:
        # 设置中文字体
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
        plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
        
        # 1. TOP20告警标题次数分析
        alarm_counts = df['告警标题'].value_counts().head(20)
        
        # 2. 标准告警级别分析
        level_counts = df['标准告警级别'].value_counts()
        
        # 3. 设备类型分析
        device_counts = df['设备类型'].value_counts().head(20)
        
        # 4. 设备厂商（虚层）分析
        vendor_counts = df['设备厂商（虚层）'].value_counts().head(20)
        
        # 如果提供了输出目录，生成柱状图
        if output_dir:
            os.makedirs(output_dir, exist_ok=True)
            print(f"创建输出目录: {output_dir}")
            
            # 生成告警标题统计图
            plt.figure(figsize=(15, 8))
            ax = sns.barplot(x=alarm_counts.values, y=alarm_counts.index)
            plt.title('TOP20告警标题次数统计')
            plt.xlabel('告警次数')
            plt.ylabel('告警标题')
            for i, v in enumerate(alarm_counts.values):
                ax.text(v, i, str(v), va='center')
            plt.tight_layout()
            plt.savefig(os.path.join(output_dir, 'top20_alarm_titles.png'))
            plt.close()
            print("生成告警标题统计图")
            
            # 生成告警级别分布图
            plt.figure(figsize=(12, 6))
            ax = sns.barplot(x=level_counts.index, y=level_counts.values)
            plt.title('告警级别分布')
            plt.xlabel('告警级别')
            plt.ylabel('数量')
            for i, v in enumerate(level_counts.values):
                ax.text(i, v, str(v), ha='center', va='bottom')
            plt.tight_layout()
            plt.savefig(os.path.join(output_dir, 'alarm_levels.png'))
            plt.close()
            print("生成告警级别分布图")
            
            # 生成设备类型分布图
            plt.figure(figsize=(15, 8))
            ax = sns.barplot(x=device_counts.values, y=device_counts.index)
            plt.title('设备类型分布')
            plt.xlabel('数量')
            plt.ylabel('设备类型')
            for i, v in enumerate(device_counts.values):
                ax.text(v, i, str(v), va='center')
            plt.tight_layout()
            plt.savefig(os.path.join(output_dir, 'device_types.png'))
            plt.close()
            print("生成设备类型分布图")
            
            # 生成设备厂商分布图
            plt.figure(figsize=(15, 8))
            ax = sns.barplot(x=vendor_counts.values, y=vendor_counts.index)
            plt.title('设备厂商（虚层）分布')
            plt.xlabel('数量')
            plt.ylabel('设备厂商（虚层）')
            for i, v in enumerate(vendor_counts.values):
                ax.text(v, i, str(v), va='center')
            plt.tight_layout()
            plt.savefig(os.path.join(output_dir, 'device_vendors.png'))
            plt.close()
            print("生成设备厂商分布图")
        
        # 准备分析结果数据
        analysis_results = {
            'top20_alarm_titles': alarm_counts.to_dict(),
            'alarm_levels': level_counts.to_dict(),
            'device_types': device_counts.to_dict(),
            'device_vendors': vendor_counts.to_dict()
        }
        
        return analysis_results
        
    except Exception as e:
        print(f"分析DataFrame时出错: {str(e)}")
        raise

def analyze_excel_file(file_path=None):
    """
    分析Excel文件并生成报告
    
    Args:
        file_path: Excel文件路径，如果为None则自动查找最新的告警导出文件
    """
    try:
        # 如果未指定文件路径，则查找最新的告警导出文件
        if file_path is None:
            file_path = find_latest_alarm_excel()
            if not file_path:
                raise FileNotFoundError("未找到告警导出Excel文件")
        
        print(f"开始分析文件: {file_path}")
        
        # 读取Excel文件
        df = pd.read_excel(file_path)
        print("Excel文件读取成功")
        
        # 创建输出目录
        output_dir = os.path.join(os.path.dirname(file_path), 'analysis_results')
        
        # 调用analyze_dataframe进行数据分析
        analysis_results = analyze_dataframe(df, output_dir)
        
        # 生成Markdown报告
        markdown_path = generate_markdown_report(
            analysis_results,
            file_path,
            output_dir
        )
        print(f"分析报告已生成: {markdown_path}")
        
        print(f"分析完成，图表已保存到: {output_dir}")
        
    except Exception as e:
        print(f"分析文件时出错: {str(e)}")
        raise

